package robotlion.model;


/**
 *
 * @author Jérémy
 */

import robotlion.view.Observateur;
import Tools.ImageConverter;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import robotlion.controller.InfoIncendie;

public class Carte extends Observable{
    private Case matrice[][];
    private ArrayList<Observateur> listObservateur = new ArrayList<Observateur>();
    
    public Carte(String imageFilePath){
        ImageConverter loader = new ImageConverter(imageFilePath);
        matrice = loader.getMatriceCarte();
    }
    
    public Carte(Case[][] mat)
    {
        matrice = mat;
    }
    
    public Carte()
    {
        matrice = new Case[0][0];
    }
    
    /**
     * Ajoute un incendie au point de coordonnées(x,y)
     * @param x : Abscisse du point
     * @param y : Ordonnée du point
     */
    public void addIncendie(int x, int y, int valIncendie){
        if (x < matrice.length && y < matrice[0].length && x >= 0 && y >= 0)
        {
            matrice[x][y].setIncendie(valIncendie);
            InfoIncendie ii = new InfoIncendie(new Point(x,y), true);
            updateObservateur(ii);
        }

    }
    
    /* Décrémente la valeur de l'incendie de valDecr à la case de coordonnées (x,y) */
    public void decrIncendie(int x, int y, int valDecr){
        matrice[x][y].setIncendie(matrice[x][y].getIncendie()-valDecr);
        if(!matrice[x][y].isIncendie())
        {
            InfoIncendie ii = new InfoIncendie(new Point(x,y), false);
            updateObservateur(ii);
        }
    }
    
    /* Décrémente la valeur de l'incendie de valDecr à la case de coordonnées (x,y) */
    public boolean isIncendie(int x, int y){
        if(matrice[x][y].isIncendie())
        {
            return true;
        }
        return false;
    }
    
    /* Retourne la largeur de la carte */
    public int getTailleX(){
        return matrice.length;
    }
    
    /* Retourne la hauteur de la carte */
    public int getTailleY(){
        return matrice[0].length;    // matrice[] contient des tableaux qui ont tous la même taille
    }
    
    /* Retourne le niveau d'accessibilité de la case de coordonnées (x,y) */
    public int getAccessibilite(int x, int y){
        return matrice[x][y].getAccessibilite();
    }
    
    /* Retourne le niveau d'accessibilité du Point donné */
    public int getAccessibilite(Point point){
        return matrice[point.x][point.y].getAccessibilite();
    }
    
    /*
     * Retourne une liste de tableaux [x,y] correspondant aux coordonnées sur la matrice des cases ou il y a des incendies
     */
    public List<int[]> getMatIncendies(){
        List listeIncendies = new ArrayList();
        for(int x = 0; x < matrice.length; x++){
            for(int y = 0; y < matrice[0].length; y++){
                if(matrice[x][y].isIncendie()){
                    int coord[] = new int[2];
                    coord[0] = x;
                    coord[1] = y;
                    listeIncendies.add(coord);
                }
            }
        }
        return listeIncendies;
    }
    
    public ArrayList<Point> getIncendies(){
        ArrayList<Point> coordonnees = new ArrayList();
        for(int x = 0; x < matrice.length; x++){
            for(int y = 0; y < matrice[0].length; y++){
                if(matrice[x][y].isIncendie()){
                    coordonnees.add(new Point(x,y));
                }
            }
        }
        return coordonnees;
    }
    
    /**
     * @param x  abscisse du point
     * @param y  ordonnée du point
     * @param niveauRobot  niveau du robot
     * @return true si le niveau du robot est supérieur ou égal au niveau du point 
     * et qu'il n'y a pas d'incendie, false sinon
     */
    public boolean praticableRobot(int x, int y, int niveauRobot){
        boolean isPraticable = true;
        if (matrice[x][y].isIncendie() || (matrice[x][y].getAccessibilite() > niveauRobot ))
            isPraticable = false;
        return isPraticable;
    }
    
    /**
     * Ajoute un observateur à la liste
     */
    public void addObservateur(Observateur obs) {
            this.listObservateur.add(obs);
    }
    
    /**
     * Retire tous les observateurs de la liste
     */
    public void delObservateur() {
            this.listObservateur = new ArrayList<Observateur>();
    }
    
    /**
     * Avertit les observateurs que l'observable a changé 
     * et invoque la méthode update de chaque observateur !
     */
    public void updateObservateur(Object info) {
        for(Observateur obs : this.listObservateur )
                obs.updateObs(info);
    }
}
